package com.trytech.mongoocrawler.client.transport.http;

import com.trytech.mongoocrawler.client.transport.http.cookie.HttpCookie;
import com.trytech.mongoocrawler.client.transport.http.cookie.HttpCookiesManager;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

/**
 * Created by coliza on 2017/8/1.
 */
public class HttpResponseProtocol extends HttpProtocol implements Serializable {
    private HttpResponseHeader header;

    public static HttpResponseProtocol parse(CrawlerHttpRequest request, URLConnection conn) {
        try {
            HttpResponseProtocol responseProtocol = new HttpResponseProtocol();
            //解析头部
            HttpResponseHeader responseHeader = new HttpResponseHeader();
            if (conn instanceof HttpURLConnection) {
                HttpURLConnection connInstance = (HttpURLConnection) conn;
                responseHeader.setStatusCode(connInstance.getResponseCode());
                responseHeader.setMessage(connInstance.getResponseMessage());
                String statusLine = (connInstance.getHeaderField(0));
                responseHeader.setHttpVersion(statusLine.substring(0, 8));
                //获取头部的各字段
                Map<String, List<String>> fieldsMap = conn.getHeaderFields();
                for (String key : fieldsMap.keySet()) {
                    if (HttpResponseHeader.HEADER_FIELDS_MAP.contains(key)) {
                        try {
                            String firstCharUpperKey = key.substring(0, 1).toLowerCase() + key.substring(1);
                            firstCharUpperKey = firstCharUpperKey.replace("-", "");
                            Field field = responseHeader.getClass().getDeclaredField(firstCharUpperKey);
                            field.setAccessible(true);
                            List valueList = fieldsMap.get(key);
                            if (valueList != null) {
                                field.set(responseHeader, StringUtils.join(valueList.iterator(), "#@SA"));
                            }
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                        }
                    }
                }
            } else {
                HttpsURLConnection connInstance = (HttpsURLConnection) conn;
                responseHeader.setStatusCode(connInstance.getResponseCode());
                responseHeader.setMessage(connInstance.getResponseMessage());
                String statusLine = (connInstance.getHeaderField(0));
                responseHeader.setHttpVersion(statusLine.substring(0, 8));
            }
            //处理response返回的写cookie命令
            String setCookie = responseHeader.getSetCookie();
            parseCookie(request, setCookie);
            responseProtocol.setHeader(responseHeader);

            InputStream input = conn.getInputStream();
            String line = "";
            BufferedReader br = new BufferedReader(new InputStreamReader(input, HttpProtocol.ENCODING));
            StringBuffer buffer = new StringBuffer();
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
            //解析body
            HttpBody body = HttpBody.parse(buffer.toString());
            responseProtocol.setBody(body);

            return responseProtocol;
        } catch (IOException e) {

        }
        return null;
    }

    private static void parseCookie(CrawlerHttpRequest request, String setCookieStr) {
        if (StringUtils.isEmpty(setCookieStr)) return;

        String[] fields = setCookieStr.split("#@SA");
        for (String field : fields) {
            HttpCookie cookie = new HttpCookie();
            cookie.setSecure(false);
            if (field.indexOf("secure") >= 0) {
                cookie.setSecure(true);
            }
            field = field.trim();
            String[] cookieFieldArr = field.split(";");
            for (String cookieField : cookieFieldArr) {
                String[] keyValArr = cookieField.split("=");
                int size = keyValArr.length;
                if (cookieField.indexOf("=") > 0) {
                    String name = cookieField.substring(0, cookieField.indexOf("=")).trim();
                    String value = cookieField.substring(cookieField.indexOf("=") + 1, cookieField.length()).trim();
                    if ("path".equalsIgnoreCase(name)) {
                        cookie.setPath(value);
                    } else if ("domain".equalsIgnoreCase(name)) {
                        cookie.setDomain(value);
                    } else if ("expires".equalsIgnoreCase(name)) {
                        cookie.setExpires(value);
                    } else {
                        cookie.setName(name);
                        cookie.setValue(value);
                    }
                }
            }
            HttpCookiesManager.addCookie(request.getSessionId(), cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(), cookie.getExpires(), cookie.isSecure());
        }
    }

    public HttpResponseHeader getHeader() {
        return header;
    }

    public void setHeader(HttpResponseHeader header) {
        this.header = header;
    }
}
